
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

using Swaf;
using Swaf.BizObj;
using Swaf.BizRule;
using Swaf.Container;
using Swaf.Security;
using UserLogin;

using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Core;

namespace UserManagement
{
    /// <summary>Provides the editing access bizrules for the UserManagement feature of the 
    /// framework gallery. The read only bizrules are contained within the UserLogin.BusinessRules
    /// class. All bizrules in this class will throw a UserManagementException 
    /// when a failure occurs.
    /// </summary>
    public class BizRules : Syrinx.BaseBizRules
    {

		public void backupCompanyUserUserGroups(IApplication app, IRuleContext context, string treeName, IBizObj deployInfo, ZipOutputStream zOut)
		{

			try
			{
				if (deployInfo == null)
					throw new UserManagementException("required parameter is missing. error executing createUserUserGroupBackup bizrule.");
				if (!(bool)deployInfo.get("fullCompanyBackup") && !(bool)deployInfo.get("includeUsers"))
					return;

                bool useDateSince = deployInfo.get("backupSince") != null;
                DateTime dateSince = DateTime.MinValue;
                if (useDateSince)
                    dateSince = (DateTime)deployInfo.get("backupSince");

				FlexiMap m = new FlexiMap();
				foreach (IBizObj company in deployInfo.get("backupCompanies") as IBizObjList)
				{
					IResults rc = context.RuleGroup.execute(context, "getCompanyUserGroups", company.get("id"));
					IBizObjList userGroups = rc.CallResults as IBizObjList;
					if (userGroups != null)
					{
						zOut.PutNextEntry(new ZipEntry(string.Format("data{0}{1}{0}CompanyUserGroups.xml", Path.DirectorySeparatorChar, company.get("shortName"))));
						byte[] bytes = Encoding.Unicode.GetBytes("<?xml version=\"1.0\" ?>\n" + userGroups.Xml.ToString());
						for (int i = 0; i < bytes.Length; i++)
							zOut.WriteByte(bytes[i]);

                        context.put("UserListFullDetails", true);
                        IBizObj filterSortOptions = null;
                        if (useDateSince)
                        {
                            filterSortOptions = app.bizObjMgr.create("FilterSortOptions");
                            IBizObj dateFilter = ((IBizObjList)filterSortOptions.get("filterOptions")).insertNew();
                            dateFilter.put("field", "dateUpdated");
                            dateFilter.put("criteria", ">");
                            dateFilter.put("value", dateSince);
                        }
						rc = context.RuleGroup.execute(context, "getCompanyUserList", company.get("id"), filterSortOptions);
						IBizObjList users = rc.CallResults as IBizObjList;
						if (users != null)
						{
							zOut.PutNextEntry(new ZipEntry(string.Format("data{0}{1}{0}CompanyUsers.xml", Path.DirectorySeparatorChar, company.get("shortName"))));
							bytes = Encoding.Unicode.GetBytes("<?xml version=\"1.0\" ?>\n" + users.Xml.ToString());
							for (int i = 0; i < bytes.Length; i++)
								zOut.WriteByte(bytes[i]);
						}
					}
				}
			}
			catch (UserManagementException ue)
			{
				throw;
			}
			catch (Exception e)
			{
				throw new UserManagementException("error executing backupCompanyUserUserGroups bizrule.", e);
			}
		}

		public void postExtendUserUserGroupexecuteCompanyBackup(IApplication app, IRuleContext context, object returnValue, object[] inputParams)
		{

			try
			{
				INameAddressSupport deployInfo = inputParams[2] as INameAddressSupport;
				ZipOutputStream zOut = inputParams[3] as ZipOutputStream;

				IResults rc = app.ruleMgr.execute(context, "backupCompanyUserUserGroups", "UserUserGroups", deployInfo, zOut);
			}
			catch (Exception e)
			{
				throw new UserManagementException("error executing postExtendProductCreateDeployment.", e);
			}
		}

		public void postExtendUserUserGroupexecuteCompanyRestore(IApplication app, IRuleContext context, object returnValue, object[] inputParams)
		{
			try
			{
				INameAddressSupport deployInfo = inputParams[2] as INameAddressSupport;
				ZipFile zipFile = inputParams[3] as ZipFile;
				IResults rc = app.ruleMgr.execute(context, "restoreCompanyUserUserGroups", deployInfo, zipFile);
				if (rc.ExceptionInfo != null)
					throw rc.ExceptionInfo;
			}
			catch (Exception e)
			{
				throw new UserManagementException("error executing postExtendProductCreateDeployment.", e);
			}
		}

		public void restoreCompanyUserUserGroups(IApplication app, IRuleContext context, IBizObj bkInfo, ZipFile zipFile)
		{
			IBizObjList restoreCompanies = (IBizObjList)bkInfo.get("restoreCompanies");
			IBizObjList backupCompanies = (IBizObjList)bkInfo.get("backupCompanies");

			//We need to change the active company id to the company that the backup is for so that
			//any reference to the activeCompanyId in the following company will point to the correct company.
			Swaf.BGuid.Guid oldCmpId = ActiveCompanyId;

			try
			{
				for (int pos = 0; pos < restoreCompanies.numElements; ++pos)
				{
					IBizObj restoreCompany = restoreCompanies[pos];
					IBizObj backupCompany = backupCompanies.numElements == 1 ? backupCompanies[0] : backupCompanies[pos];
					bool restoreToSameCompany = string.Compare((string)backupCompany.get("shortName"), (string)restoreCompany.get("shortName")) == 0;
					ActiveCompanyId = restoreCompany.get("id") as Swaf.BGuid.Guid;
					IResults rc = null;
					IBizObj adminGroup = null;

					try
					{
						int numFilesFound = 0;
						Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid> m_idDict = context.get("IdMap" + restoreCompany.get("shortName")) as Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid>;
						if (m_idDict == null)
							context.put("IdMap" + restoreCompany.get("shortName"), m_idDict = new Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid>());
						string userGroupsFileName = string.Format("data{0}{1}{0}CompanyUserGroups.xml", Path.DirectorySeparatorChar, backupCompany.get("shortName"));
						string usersFileName = string.Format("data{0}{1}{0}CompanyUsers.xml", Path.DirectorySeparatorChar, backupCompany.get("shortName"));
						foreach (ZipEntry entry in zipFile)
						{
							string entryName = entry.Name;
							bool isUserGroups = false;
							if (entry.IsFile && (isUserGroups = entryName.CompareTo(userGroupsFileName) == 0) ||
								entryName.CompareTo(usersFileName) == 0)
							{
								StreamReader sr = new StreamReader(zipFile.GetInputStream(entry), Encoding.Unicode);
								string file = sr.ReadToEnd();
								IBizObjList items = app.bizObjMgr.createList(SourceType.BasicSource, file, isUserGroups ? "UserGroup" : "User", null);
								foreach (IBizObj item in items)
								{
									//When restoring a backup to the SAME company the backup was created from, the ids should
									//not be reset.  That way, we will restore OVER EXISTING data, which is what would
									//be wanted when restoring a backup in the same company.
									if (!restoreToSameCompany)
									{
										Swaf.BGuid.Guid g = null;
										if (!m_idDict.TryGetValue(item.get("id") as Swaf.BGuid.Guid, out g))
											m_idDict.Add(item.get("id") as Swaf.BGuid.Guid, g = new Swaf.BGuid.Guid());
										item.put("id", g);
									}
									item.put("companyId", ActiveCompanyId);
									if (isUserGroups)
									{
                                        
                                        //int systemType = (int)item.get("systemType");
                                        //if (systemType == (int)UserGroupSystemType.Admin)
                                        //    adminGroup = item;

                                        //rc = context.RuleGroup.execute(context, "deleteGroup", item.get("id"));
                                        //rc = context.RuleGroup.execute(context, "updateGroup", item);
									}
									else
									{
										item.put("settings.id", item.get("id"));
										if (item.get("contact.id") != null)
										{
											item.put("contact.companyId", ActiveCompanyId);
											item.put("contact.id", item.get("id"));
										}
										IBizObjList userUserGroups = (IBizObjList)item.get("groups");
										for (int pos2 = 0; pos2 < userUserGroups.numElements; pos2++)
										{
											IBizObj userUserGroup = userUserGroups[pos2];
											userUserGroup.put("companyId", ActiveCompanyId);
											Swaf.BGuid.Guid usrGroupId = userUserGroup.get("id") as Swaf.BGuid.Guid;
											if (m_idDict.ContainsKey(usrGroupId))
												userUserGroup.put("id", m_idDict[usrGroupId]);
											else if (!restoreToSameCompany)
												userUserGroups.removeAt(pos2--);
										}
                                        item.put("dateUpdated", item.get("dateUpdated"));
                                        item.put("dateCreated", item.get("dateCreated"));
										rc = context.RuleGroup.execute(context, "deleteUser", item.get("userName"));
										rc = context.RuleGroup.execute(context, "updateUserInfo", item);
										rc = context.RuleGroup.execute(context, "setUserUserGroupMembership", item.get("id"), (IBizObjList)null, item.get("groups"));
										if ((bool)item.get("isCompanyDefaultAnonymousUser"))
										{
											restoreCompany.put("anonymousId", item.get("id"));
											app.appData.put("DA.UserManagement.SetCompanyAnonymousId", restoreCompany);
										}
									}
								}
								if (++numFilesFound == 2)
									break;
							}
						}

						IBizObjList newAdminUsers = bkInfo.get("restoreAdditionalUsers") as IBizObjList;
						if (newAdminUsers != null)
						{
							foreach (IBizObj newAdminUser in newAdminUsers)
							{
								newAdminUser.put("id", new Swaf.BGuid.Guid());
								newAdminUser.put("companyId", restoreCompany.get("id"));
								((IBizObjList)newAdminUser.get("groups")).Add(adminGroup);
								rc = context.RuleGroup.execute(context, "setupUserProfile", newAdminUser);
							}
						}

						//string anonu = string.Format("{0}anonymous", newCompany.get("shortName"));
						//IBizObj newAnonUser = app.bizObjMgr.create("User");
						//newAnonUser.put("userName", "anonymous");
						//newAnonUser.put("password", "anonpassword");
						//((IBizObjList)newAnonUser.get("groups")).Add(app.appData["userLoginOptions.defaultAnonymousUserGroup"] as IBizObj);


					}
					catch (Exception e)
					{
						throw new UserManagementException("error executing restoreBackUpOnUserUserGroups", e);
					}
				}
			}
			finally
			{
				ActiveCompanyId = oldCmpId;
			}
		}

		
		/// <summary>
        /// Verifies that the current user's active company can have new users or companies
        /// created via direct user signup rather then having to have an administrator 
        /// manually perform the process. This bizrule is typically used by the UI to
        /// control the exposure of "sign up now" type UI elements.
        /// </summary>
        /// <param name="checkCompany">If true, this bizrule will check if the given company
        /// can have child companies be "auto created".  If false this bizrule will
        /// check if the given comapny can have child users be "auto created".</param>
        /// <returns>True if the given company can have child companies/users
        /// created</returns>
		public bool canAutoCreate(IApplication app, IRuleContext context, bool checkCompany)
		{
			try
			{
				FlexiMap m = new FlexiMap();
				m.put("companyId", ActiveCompanyId);
				IBizObj company = app.appData.get("DA.UserLogin.GetCompany", m) as IBizObj;
				if (company != null)
					return ((bool)company.get("enable") && (bool)company.get((checkCompany)?"autoCreateCompany":"autoCreateUser"));
				else
					return false;
			}
			catch (Exception e)
			{
				throw new UserManagementException("Error executing canAutoCreate bizrule.", e);
			}
		}
		public bool isUserNameUnique(IApplication app, IRuleContext context, string userName)
		{
			return getUserFromUserName(app, context, userName) == null;
		}

		public IBizObj getUserFromUserName(IApplication app, IRuleContext context, string userName)
		{
			FlexiMap m = new FlexiMap();
			m.put("companyId", ActiveCompanyId);
			m.put("userName", userName);
			IBizObj user = app.appData.get("DA.UserLogin.GetUserByLogin", m) as IBizObj;
			return user;
		}


		public bool isShortNameUnique(IApplication app, IRuleContext context, string shortName)
		{
			FlexiMap m = new FlexiMap();
			m.put("companyId", ActiveCompanyId);
			m.put("shortName", shortName);
			IBizObj company = app.appData.get("DA.UserLogin.GetCompanyByShortName", m) as IBizObj;
			if (company == null)
				return true;
			return false;
		}
        /// <summary>
        /// This bizrule will verify that a root company exists in the data store and if
        /// it doesn't, it will setup a root company based on the generic information 
        /// that exists in the UserManagementFeature.xml.  This bizrule is typically
        /// called at the startup of the application in order to ensure that some data is in
        /// the data store.  If the application is started with no data in the data store
        /// then this method will ensure that a generic admin/anonymous user can be logged
        /// in to configure the application through the UI.
        /// </summary>
		public void checkRootCompany(IApplication app, IRuleContext context)
        {
            try
            {
                Debug.Assert(app.appData.get("userLoginOptions.rootCompanyId") != null);
				FlexiMap m = new FlexiMap();
                m.put("companyId", app.appData.get("userLoginOptions.rootCompanyId"));
                IBizObj company = app.appData.get("DA.UserLogin.GetCompany", m) as IBizObj;

                //check if db is empty and create root company if it is
                if (company == null)
                {
                    IResults rc = app.ruleMgr.execute("createCompany", null, null, null, null, null, null);
                    if (rc.ExceptionInfo != null)
                        throw new UserManagementException("Error creating root company.", rc.ExceptionInfo);
                }
            }
            catch (UserManagementException) { throw; }
            catch (Exception e)
            {
                throw new UserManagementException("Error  while looking for root company.", e);
            }
        }
       
        /// <summary>
        /// This bizrule will create a new user group in the datastore given some basic info
        /// within the given UserGroup bizobj.  This bizrule will create the user group's
        /// unique id, set its companyId to the current user's active company id and set
        /// the basic dateCreate/createdBy properites.
        /// </summary>
        /// <param name="group">The basic user group information such as name and
        /// description to use to populate the data store with.</param>
        public void addGroup(IApplication app, IRuleContext context, IBizObj userGroup)
        {
            if(userGroup == null)
                throw new UserManagementException("userGroup cannot be null.");

            try
            {
                userGroup.put("companyId",  ActiveCompanyId);
                userGroup.put("dateCreated", DateTime.Now.ToUniversalTime());
                userGroup.put("createdBy", CurrentUser.get("id"));
				if (!userGroup.isFieldSet("id"))
					userGroup.put("id",Swaf.BGuid.Guid.NewGuid());
                IBizObjList ug = app.appData.get("Data.UserManagement.ValidateCompanyUserGroup",userGroup) as IBizObjList;
                Debug.Assert(ug != null);
                if (ug.numElements > 0 && ug[0].get("name") != ug[0].type.getField("name",true).SampleValue)
                    throw new UserManagementException("Record Not Saved. User Group Already Exist.");
				app.appData.put("Data.UserManagement.AddGroup", userGroup);
                setUserGroupPrivileges(app, userGroup);
            }
            catch (UserManagementException) { throw; }
            catch (Exception e)
            {
                throw new UserManagementException("Error executing appData.get(Data.Adm-AddGroup)", e);
            }
        }

		public void updateUserGroupAppFunctions(IApplication app, IRuleContext context, Swaf.BGuid.Guid groupId, IBizObj priv)
		{
			try
			{
				IBizObj selectGrp = context.RuleGroup.execute(context, "getUserGroupDetails", groupId).CallResults as IBizObj;
				if (selectGrp == null)
				{
					//We are assuming that if we cannot find a real user group with the given group id that we are 
					//actually being given a userid.  Each user can have their own privelges and we dont really want
					//a user group created for them.  We still call updateGroup bizrule to setup the privelegs, but
					//we dont want it to try and create a user group.  We can control that by clearing the new/dirty
					//flags.
					selectGrp = app.bizObjMgr.create("UserGroup");
					selectGrp.put("id", groupId);
					selectGrp.isNew = false;
					selectGrp.clearDirtyFlags();
				}
				IBizObj af = ((IBizObjList)selectGrp.get("appPrivileges")).search("id", priv.get("id").ToString());
				if (af == null)
					af = ((IBizObjList)selectGrp.get("appPrivileges")).insertNew();
				af.put("id", priv.get("id"));
				af.put("privilege", priv.get("privilege"));
				IResults rc = app.ruleMgr.execute(context,"updateGroup", selectGrp);
			if (rc.ExceptionInfo != null)
				throw new UserManagementException("error executing updatGroup from updateUserGroupAppFunctions.", rc.ExceptionInfo);
			}catch(Exception e)
			{
				throw new UserManagementException("error executing updateUserGroupAppFunctions bizrule.", e);
			}
		}

        /// <summary>
        /// This bizrule will update the given user group within the data store.  This bizrule
        /// will set the user group's dateUpdated/updatedBy properties.
        /// </summary>
        /// <param name="group">The user group info to update the data store with</param>
        public void updateGroup(IApplication app, IRuleContext context, IBizObj userGroup)
        {
            if (userGroup == null)
                throw new UserManagementException("userGroup cannot be null.");

            try
            {
				if (userGroup.isNew)
					addGroup(app, context, userGroup);
				else
				{
					if (userGroup.isDirty())
					{
						userGroup.put("dateUpdated", DateTime.Now);
						userGroup.put("updatedBy", CurrentUser.get("id"));

						app.appData.get("Data.UserManagement.UpdateGroup", userGroup);
					}
					setUserGroupPrivileges(app, userGroup);

					LoginMgr.userGroupUpdated(userGroup);
				}
            }
            catch (Exception e)
            {
                throw new UserManagementException("Error executing appData.get(Data.Adm-UpdateGroup)", e);
            }
        }

		public void deleteCompany(IApplication app, IRuleContext context, Swaf.BGuid.Guid companyId)
		{
		}

        /// <summary>
        /// This bizrule will remove the given user group from the data store and remove all
        /// user relationships and security privileges associated to it.
        /// </summary>
        /// <param name="group">the user group id to remove.</param>
        public void deleteGroup(IApplication app, IRuleContext context, object userGroupId)
        {
            if (userGroupId == null)
                throw new UserManagementException("userGroupId param cannot be null");

            try
            {
				if (userGroupId is string)
				{//
					FlexiMap m = new FlexiMap();
					m.put("companyId", ActiveCompanyId);
					m.put("name", userGroupId);
					IBizObj userGroupx = app.appData.get("DA.UserLogin.GetUserGroupIdFromUserGroupName", m) as IBizObj;
					if (userGroupx == null)
						return; //No need to do any more if there is no user with the provided id.

					userGroupId = userGroupx.get("id");
				}

                IBizObj userGroup = app.bizObjMgr.create("UserGroup");
                userGroup.put("id", userGroupId);
                app.appData.get("Data.UserManagement.ClearGroupPrivileges", userGroup);
                app.appData.get("DA.UserManagement.DeleteUserGroupLink", userGroup);
                app.appData.get("Data.UserManagement.DeleteGroup", userGroup);

                LoginMgr.userGroupDeleted(userGroup);
            }
            catch (Exception e)
            {
				throw new UserManagementException("Error executing appData.get(Data.UserManagement.DeleteGroup)", e);
            }

        }
       
        /// <summary>
        /// this bizrule handles the creation of a new user and userGroup.
		/// the userbiz obj should be defined correctly, that is the companyId of the user
		/// should be the activeCompanyId of the active user.
        /// </summary>
        /// <param name="user">new user information</param>
        /// <param name="groups">user groups membership</param>
        public void setupUserProfile(IApplication app, IRuleContext context, IBizObj user)
        {
            if (user == null)
                throw new UserManagementException("The user param cannot be null.");

            try
            {
                IBizObj existingUser = (IBizObj)app.appData.get("DA.UserLogin.GetUserByLogin", user);
				if (existingUser == null)
				{
                    DateTime n = DateTime.UtcNow;
					if (!user.isDirty("dateCreated"))
						user.put("dateCreated", n);
                    if (!user.isDirty("dateUpdated"))
                        user.put("dateUpdated", n);
                    app.appData.put("Data.UserManagement.CreateUser", user);
					IBizObjList groups = user.get("groups") as IBizObjList;
					if (groups.numElements > 0)
					{
						FlexiMap map = new FlexiMap();
						foreach (IBizObj group in groups)
						{
							map.put("id", group.get("id"));
							IBizObjList l = (IBizObjList)app.appData.get("Data.UserLogin.GetUserGroup", map);

							if (l.Count == 0)
							{
								app.appData.put("Data.UserManagement.AddGroup", group);
								setUserGroupPrivileges(app, group);
							}
						}
						user.put("groups", groups);
						setUserUserGroupMembership(app, context, (Swaf.BGuid.Guid)user.get("id"), null, groups);
					}
				}
				else
					throw new UserAlreadyExists(user.get("userName"));
            }
            catch (UserManagementException e) { throw e; }
            catch (Exception e)
            {
                throw new UserManagementException("Error executing initializedDefaultUserProfile", e);
            }
        }

		/// <summary>
		/// this method will remove a given user from database including its
		/// user group link information.
		/// </summary>
		/// <param name="user">user to be deleted</param>
		public void deleteUser(IApplication app, IRuleContext context, object id)
		{
			try
			{
				FlexiMap m = new FlexiMap();
				if (id is string)
				{
					m.put("companyId", ActiveCompanyId);
					m.put("userName", id);
					IBizObj user = app.appData.get("DA.UserLogin.GetUserByLogin", m) as IBizObj;
					if (user == null)
						return; //No need to do any more if there is no user with the provided id.

					id = user.get("id");
				}

				m.put("id", id);
				app.appData.put("DA.UserManagement.ClearUserUserGroupLink", m);
				app.appData.put("DA.UserManagement.DeleteUserSettings", m);
				app.appData.put("DA.UserManagement.DeleteUser", m);
				context.RuleGroup.execute(context, "deleteContact", id);
			}
			catch (Exception e)
			{
				throw new UserManagementException("deleteUser bizRule error.", e);
			}
		}

        /// <summary>
        /// this bizRule handles the creation of a new company 
        /// and default company profiles(admin,admin group, anonymous, anonymous group
        /// </summary>
        /// <param name="companyName">name of the company</param>
        /// <param name="parentId">Guid of the parent company. this should be coming from the page. 
        ///     If null this will trigger creation of the default company if none is yet
        ///     setup in the database
        /// </param>
        /// <param name="adminUserName">admin username. if null will default to admin</param>
        /// <param name="adminPassword">admin user password. if null will default to admin</param>
        /// <param name="anonUserName">anonymous username. if null will be defaulted to anonymous</param>
        /// <param name="anonPassword">anoymous user password.if null will be set to anonymous</param>
        /// <returns>this is the instance of the newly created company bizObj</returns>
		/// 
		public IBizObj createCompany(IApplication app, IRuleContext context,  string companyName, Swaf.BGuid.Guid parentId, 
			string adminUserName, string adminPassword, string anonUserName, string anonPassword)
		{
			IBizObj company = app.bizObjMgr.create("Company");
			company.put("parentId", parentId);
			IBizObj root = app.bizObjMgr.create("User");
			IBizObj anon = app.bizObjMgr.create("User");
			root.put("userName", adminUserName);
			root.put("password", adminPassword);
			anon.put("userName", adminUserName);
			anon.put("password", adminPassword);
			anon.put("userName", adminUserName);
			anon.put("password", adminPassword);
			return newCompanySignUp(app, context, company, root, anon, false);
		}

		public IBizObj newCompanySignUp(IApplication app, IRuleContext context,IBizObj company,IBizObj rootUser,IBizObj anonUser,bool isSignUp)
		{
			try
			{
				if (company == null)
					return null;
				if (company.get("parentId") == null)
					if ((bool)app.appData.get("userLoginOptions.autoPopulateBlankDataSource"))
						if (((IBizObjList)app.appData.get("Data.UserLogin.GetDefaultCompany", new FlexiMap())).numElements > 0)
							throw new UserManagementException("Error creating company with null parent id. Default company already exist in the database.");
						else
							return defineNewCompanyProfile(app, null, null, null, null, null, null);
					else
						throw new Exception("Current App Config does not allow autoPopulateBlankDataSource");
				else
					if (true.Equals(ActiveCompany.get("canCreateChildCompanies")))
					{
						if (isSignUp)
							return defineNewCompanyProfileFromSignUp(app, company, rootUser, anonUser);
						else
						{
							string cn = company.get("name").ToString();
							string rn = rootUser.get("userName").ToString();
							string rp = rootUser.get("password").ToString();
							string an = anonUser.get("userName").ToString();
							string ap = anonUser.get("password").ToString();
							Swaf.BGuid.Guid pid = company.get("parentId") as Swaf.BGuid.Guid;
							return canUserManageCompany(app, pid)
								? defineNewCompanyProfile(app, pid, cn, rn, rp, an, ap)
								: null;
						}
					}
					else
						return null;
			}
			catch (UserManagementException) { throw; }
			catch (Exception e)
			{
				throw new UserManagementException("Error executing createCompany.", e);
			}
		}

		protected void setupDefaultUsers(out IBizObj adminUser, out IBizObj anonUser)
		{
			adminUser = App.bizObjMgr.create("User");
			adminUser.put("id", new Swaf.BGuid.Guid());
			adminUser.put("userName", "admin");
			adminUser.put("password", "p@ssword");

			anonUser = App.bizObjMgr.create("User");
			anonUser.put("id", new Swaf.BGuid.Guid());
			anonUser.put("userName", "anon");
		}

		public void updateCompany(IApplication app, IRuleContext context, IBizObj company)
		{
            if (company == null)
                throw new UserManagementException("The company param cannot be null.");

			try
			{
				if (company.isNew)
				{
					IBizObj root, anon;
					setupDefaultUsers(out root, out anon);
					newCompanySignUp(app, context, company, root, anon, true);
				}
				else
				{
					app.appData.get("Data.UserManagement.UpdateCompany", company);
					company.put("treeName", "company");
					IResults rc = app.ruleMgr.execute(context, "renameBizObjInTree", company, "");
					if (rc.ExceptionInfo != null)
						throw new Exception("Error executing renameBizOjbInTree bizrule from updateCompany", rc.ExceptionInfo);

					IBizObj settings = company.get("settings") as IBizObj;
					if (settings.isNew)
						app.appData.put("DA.UserManagement.InsertCompanySettings", settings);
					else
						app.appData.put("DA.UserManagement.UpdateCompanySettings", company.get("settings"));

					app.ruleMgr.execute("clearCachedCompanyInfo", ActiveCompanyId);
					app.ruleMgr.execute("updateContact", company.get("contact"), false);
				}
			}
			catch (UserManagementException)
			{
				throw;
			}
			catch (Exception e)
			{
				throw new UserManagementException("Error executing updateCompany bizRule.", e);
			}
		}
		protected IBizObj defineNewCompanyProfileFromSignUp(IApplication app, IBizObj company, IBizObj rootUser, IBizObj anonUser)
		{
			try
			{
				if(!company.isDirty("id"))
					company.put("id", (company.get("parentId") == null)
						? app.appData.get("userLoginOptions.rootCompanyId") 
						: Swaf.BGuid.Guid.NewGuid());
				company.put("enable", true);

				if (rootUser != null)
				{
					IBizObj adminGrp = (IBizObj)((IBizObj)app.appData.get("userLoginOptions.defaultAdminUserGroup")).Clone();
					rootUser.put("id", Swaf.BGuid.Guid.NewGuid());
					rootUser.put("companyId", company.get("id"));
					rootUser.put("enable", true);

					adminGrp.put("id", Swaf.BGuid.Guid.NewGuid());
					adminGrp.put("companyId", company.get("id"));
					adminGrp.put("dateCreated", DateTime.Now);
					adminGrp.put("createdBy", rootUser.get("id"));

					IBizObjList adminGrps = app.bizObjMgr.createList("UserGroup");
					adminGrps.Add(adminGrp);
					rootUser.put("groups", adminGrps);
					app.ruleMgr.execute("setupUserProfile", rootUser);
				}

				if (anonUser != null)
				{
					IBizObj anonGrp = (IBizObj)((IBizObj)app.appData.get("userLoginOptions.defaultAnonymousUserGroup")).Clone();
					anonUser.put("id", Swaf.BGuid.Guid.NewGuid());
					anonUser.put("companyId", company.get("id"));
					anonUser.put("enable", true);
					anonGrp.put("id", Swaf.BGuid.Guid.NewGuid());
					anonGrp.put("companyId", company.get("id"));
					anonGrp.put("dateCreated", DateTime.Now);
					anonGrp.put("createdBy", rootUser.get("id"));

					IBizObjList anonGrps = app.bizObjMgr.createList("UserGroup");
					anonGrps.Add(anonGrp);
					anonUser.put("groups", anonGrps);
					app.ruleMgr.execute("setupUserProfile", anonUser);

					company.put("anonymousId", anonUser.get("id"));
				}

				app.appData.put("DA.UserManagement.CreateCompany", company);


				if (company.get("parentId") == null)
					company.put("parentId", company.get("id"));
				company.put("treeName", "company");
				IResults rc = app.ruleMgr.execute("insertBizObjIntoTree", company, true);
				if (rc.ExceptionInfo != null)
					throw new UserManagementException(string.Format("error executing insertBizObjIntoTree for createNewAccount.{0}", company.Xml), rc.ExceptionInfo);

				return company;
			}
			catch (Exception e)
			{
				throw new UserManagementException("Error executing defineNewCompanyProfileFromSignUp bizrule", e);
			}

		}

		protected IBizObj defineNewCompanyProfile(IApplication app, Swaf.BGuid.Guid parentId, string companyName, string adminUserName, string adminPassword, string anonUserName, string anonPassword)
        {
			try
			{

				IBizObj company = (IBizObj)app.appData.get("userLoginOptions.defaultCompany");
				IBizObj admin = (IBizObj)app.appData.get("userLoginOptions.defaultAdminUser");
				IBizObj anon = (IBizObj)app.appData.get("userLoginOptions.defaultAnonymousUser");

				IBizObj anonGrp = (IBizObj)app.appData.get("userLoginOptions.defaultAnonymousUserGroup");
				IBizObj adminGrp = (IBizObj)app.appData.get("userLoginOptions.defaultAdminUserGroup");
				
				company.put("parentId", parentId);
				if (companyName != null && companyName.Length != 0)
					company.put("name", companyName);
				if (anonUserName != null && anonUserName.Length != 0)
					anon.put("userName", anonUserName);
				if (anonPassword != null && anonPassword.Length != 0)
					anon.put("password", anonPassword);
				if (adminUserName != null && adminUserName.Length != 0)
					admin.put("userName", adminUserName);
				if (adminPassword != null && adminPassword.Length != 0)
					admin.put("password", adminPassword);
				return defineNewCompanyProfileFromSignUp(app, company, admin, anon);
				
			}
			catch (Exception e)
			{
				throw new UserManagementException("Error executing setupDefaultCompanyProfile bizrule", e);
			}
        }
		
        public void updateUserPassword(IApplication app, IRuleContext context, string newPassword, IBizObj user)
        {
            if (user == null || newPassword == null)
                throw new UserManagementException("The user and newPassword params cannot be null.");

            try
            {
                user.put("password", newPassword);
				app.appData.get("Data.UserManagement.ChangePassword", user);
            }
            catch (Exception e)
            {
                throw new UserManagementException("Error executing appData.get(Data.Adm-ChangePassword DAR", e);
            }
        }

		public void updateUserInfo(IApplication app, IRuleContext context, IBizObj user)
        {
            if (user == null)
                throw new UserManagementException("The user param cannot be null.");

            try
            {
				user.put("dateUpdated", DateTime.Now.ToUniversalTime());
				if (user.isNew)
				{
					if (!user.isFieldSet("id"))
						app.appData.put("id", Swaf.BGuid.Guid.NewGuid());
					if(!user.isDirty("dateCreated"))
						user.put("dateCreated", DateTime.Now.ToUniversalTime());
					app.appData.put("DA.UserManagement.CreateUser", user);
				}
				else
					app.appData.put("DA.UserManagement.UpdateUser", user);
				//app.appData.get(string.Format("DA.UserManagement.{0}", user.isNew ? "CreateUser" : "UpdateUser"), user);
               // setUserUserGroupMembership(app,context,user);
				if (CurrentPrincipal.getPrivilege("AppFunctions.ManageUsers") > Privileges.ReadOnly)
					app.appData.put("DA.UserManagement.UpdateUserLimits", user.get("limits"));

				bool doUserSettingsInsert = true;
				if (!user.isNew)
				{
					int cnt = (int)app.appData.get("DA.UserManagement.UpdateUserSettings", user.get("settings"));
					if (cnt != 0)
						doUserSettingsInsert = false;
				}

				if(doUserSettingsInsert)
					app.appData.put("DA.UserManagement.InsertUserSettings", user.get("settings"));

				if (user.get("contact.id") != null)
				{
					IResults rc = context.RuleGroup.execute(context, "updateContact", user.get("contact"), false);
					if (rc.ExceptionInfo != null)
						throw rc.ExceptionInfo;
				}
			}
            catch (Exception e)
            {
                throw new UserManagementException("Error executing appData.get(Data.Adm-UpdateUser)", e);
            }
        }

		public Swaf.BGuid.Guid getUserCompanyId(IApplication app, IRuleContext context, Swaf.BGuid.Guid userId)
		{
			FlexiMap m = new FlexiMap();
			m.put("userId", userId);
			IBizObj company = app.appData.get("DA.UserLogin.GetUserCompanyId", m) as IBizObj;
			return company == null ? null : company.get("id") as Swaf.BGuid.Guid;
		}

		public IBizObj getUser(IApplication app, IRuleContext context, Swaf.BGuid.Guid userId)
		{
			try
			{
				//First parallel execute the request to get the preferences and contact details.  These
				//rules could be remote calls and take longer than expected.
				object[] callParams = new object[]{userId};
				IRuleGroup rg = app.ruleMgr.executeAsync(context, "getUserPreferences", null, "", callParams);
				rg.executeAsync(context, "getContactDetail", null, "", callParams);

				//While the two parallel rules execute, get the basic user info using the DAR call.
				FlexiMap m = new FlexiMap();
				m.put("userId", userId);
				IBizObj user = app.appData.get("DA.UserLogin.GetUserDetails", m) as IBizObj;
				if (user == null)
					throw new UserManagementException("Unable to find user with provided id");
				IBizObj limits = app.appData.get("DA.UserLogin.GetUserLimits", m) as IBizObj;
				if (limits == null)
					throw new UserManagementException("Unable to find user with provided id");
				user.put("limits", limits);

				//Wait for the child rules to complete before assembling the final user info.
				rg.waitForCompletion(false);

				if (rg.getCallResults(0) != null && rg.getCallResults(0) is IBizObj)
					user.put("settings", (IBizObj)rg.getCallResults(0));
				else if (rg.getExceptionInfo(0) != null)
					throw rg.getExceptionInfo(0);
				else
					((IBizObj)user.get("settings")).isNew = true;

				if (rg.getCallResults(1) != null && rg.getCallResults(1) is IBizObj)
					user.put("contact", (IBizObj)rg.getCallResults(1));
				else if (rg.getExceptionInfo(1) != null)
					throw rg.getExceptionInfo(1);
				else
					((IBizObj)user.get("contact")).isNew = true;

				return user;
			}
			catch (UserManagementException)
			{
				throw;
			}
			catch (Exception e)
			{
				throw new UserManagementException("Error executing getUser bizrule", e);
			}
		}

        public IBizObj getUserGroupDetails(IApplication app, IRuleContext context, Swaf.BGuid.Guid userGroupId)
        {
			if (userGroupId == null)
				throw new UserManagementException("Invalid value passed for userGroupId");
			try
            {
				FlexiMap m = new FlexiMap();
				m.put("userGroupId", userGroupId);
                IBizObj userGroup = app.appData.get("DA.UserManagement.GetUserGroupDetails", m) as IBizObj;
                return userGroup;
            }
            catch (Exception e)
            {
                throw new UserManagementException("Error executing getUseruserGroupList", e);
            }
        }
		public IBizObjList getCompanyUserGroups(IApplication app, IRuleContext context, Swaf.BGuid.Guid companyId)
		{
			if (companyId == null)
				companyId = ActiveCompanyId;
			FlexiMap m = new FlexiMap();
			m.put("companyId", companyId);
			IBizObjList list = (IBizObjList)app.appData.get("DA.UserManagement.GetCompanyUserGroups", m);
			return list;
		}
        public IBizObjList getCompanyUserGroupList(IApplication app, IRuleContext context, Swaf.BGuid.Guid companyId)
        {

			try
			{
				return getCompanyUserGroups(app, context, companyId);
			}
			catch (Exception e)
			{
				throw new UserManagementException("Error executing getUseruserGroupList", e);
			}
			//return filterCompanyUserGroupAppFunction(app, context, companyId, null);
        }
		public IBizObjList getUserUserGroups(IApplication app, IRuleContext context, Swaf.BGuid.Guid id)
		{
			try
			{
				FlexiMap m = new FlexiMap();
				m.put("userId", id);
				IBizObjList userGroups = (IBizObjList)app.appData.get("DA.UserLogin.GetUserUserGroups", m);
				return userGroups;
			}
			catch (Exception e)
			{
				throw new UserManagementException("Error executing getUserUserGroups", e);
			}
		}

		public IBizObjList getCompleteUserGroupListWithUserMembership(IApplication app, IRuleContext context, Swaf.BGuid.Guid companyId, Swaf.BGuid.Guid userId)
		{
			IRuleGroup rg = app.ruleMgr.executeAsync(context, "getCompanyUserGroupList", null, "", new object[] { companyId });
			rg.execute(context, "getUserUserGroups", null, "", new object[] { userId });
			rg.waitForCompletion(true);

			if (rg.getCallResults(0) is IBizObjList && rg.getCallResults(1) is IBizObjList)
			{
				IBizObjList companyUserGroups = rg.getCallResults(0) as IBizObjList;
				IBizObjList userUserGroupMembership = rg.getCallResults(1) as IBizObjList;
				foreach (IBizObj obj in userUserGroupMembership)
				{
					IBizObj ug = companyUserGroups.search("id", obj.get("id") as Swaf.BGuid.Guid);
					if (ug != null)
						ug.put("checked", true);
				}
				return companyUserGroups;
			}
			else if (rg.getExceptionInfo(0) != null)
				throw rg.getExceptionInfo(0);
			else if (rg.getExceptionInfo(1) != null)
				throw rg.getExceptionInfo(1);
			throw new UserManagementException("Unable to retriever user or company user group information");
		}

        public IBizObjList getCompanyUserList(IApplication app, IRuleContext context, Swaf.BGuid.Guid companyId, IBizObj criteria)
        {
            if (companyId == null)
                throw new UserManagementException("The companyId param cannot be null.");

            try
            {
				bool getFullDetails = context.get("UserListFullDetails") is bool?(bool)context.get("UserListFullDetails"):false;
				DetailLevel detailLevel = getFullDetails ? DetailLevel.fullDetails : DetailLevel.basicDetails;
				IResults rc = context.RuleGroup.execute(context, "getContacts", detailLevel, companyId, app.appData.get("CompanyUserContactsFilter"));
				IBizObjList companyContacts = rc.CallResults as IBizObjList;
				FlexiMap m = new FlexiMap();
				m.put("companyId", companyId);
                m.put("criteria", criteria);
                IBizObjList companyUsers = app.appData.get(
					getFullDetails ? "DA.UserLogin.GetCompanyUsersWithFullDetail" : "DA.UserLogin.GetCompanyUsers", m) as IBizObjList;
				IBizObj forCompany = context.RuleGroup.execute("getCachedCompanyInfo", companyId).CallResults as IBizObj;
				Swaf.BGuid.Guid companyAnonId = forCompany.get("anonymousId") as Swaf.BGuid.Guid;
				foreach (IBizObj user in companyUsers)
				{
					IBizObj contact = companyContacts.search("id", user.KeyValue);
					if (contact != null)
						user.put("contact", contact);
					if (companyAnonId == (Swaf.BGuid.Guid)user.get("id"))
						user.put("isCompanyDefaultAnonymousUser", true);
					user.clearDirtyFlags();
					user.isNew = false;
				}
				return companyUsers;
            }
            catch (Exception e)
            {
                throw new UserManagementException("Error executing getUseruserGroupList", e);
            }
        }

		/// <summary>
		/// when creating a new template for the filterSortOption bizObj. The display should adhere to what is currently
		/// supported field value that is used in comparing the filter option criteria
		/// the current implementation supports (ALL and userGroup) any other field included in the filter options shouldbe added 
		/// on this code for the filter to work properly.
		/// </summary>
		/// <param name="app"></param>
		/// <param name="context"></param>
		/// <param name="userGroup"></param>
		/// <param name="filterSortCriteria"></param>
		/// <returns></returns>
		public IBizObjList filterCompanyUserGroupAppFunction(IApplication app, IBizObj userGroup, IBizObj filterSortCriteria)
		{
			try
			{
				if (userGroup == null)
					throw new Exception("required parameter companyId is null");
				FlexiMap m = new FlexiMap();
				m["criteria"] = string.Format("g.companyId = '{0}'", userGroup.get("companyId"));
				if (filterSortCriteria != null)
				{
					IBizObjList options = filterSortCriteria.get("filterOptions") as IBizObjList;
					foreach (IBizObj option in options)
					{
						//TODO: make this bizrule more generic
						if (option.get("field").ToString().ToUpper() == "ALL")
							break;
						if ("usergroup".Equals(option.get("field").ToString().ToLower()))
						{
							string val = option.get("value").ToString();
							int i = Convert.ToInt16(option.get("criteria"));
							if (i == 1)
								m["criteria"] = string.Format("g.name='{0}'", val);
							else if (i == 2)
								m["criteria"] = string.Format("like '%{0}%'", val);
							else if (i == 3)
								m["criteria"] = string.Format("like '{0}%'", val);
							else if (i == 4)
								m["criteria"] = string.Format("like '%{0}'", val);
						}
						else
							continue;
					}
				}
				IBizObjList list = (IBizObjList)app.appData.get("Data.UserManagement.GetCompanyUserGroups", m);
				return list;
			}
			catch (Exception e)
			{
				throw new UserManagementException("Error executing filterCompanyUserGroupAppFunction bizrule.", e);
			}
		}

        /// <summary>
        /// this method will update the userGroup appFunction privilege information.
        /// the dar call will delete the entry of the said privilege and insert back the
        /// new privilege information of the given userGroup.
        /// and update the in memory representation of given userGrp
        /// </summary>
        /// <param name="userGrp">userGrp with appPrivilege to be updated</param>
        protected void setUserGroupPrivileges(IApplication app, IBizObj userGrp)
        {
            FlexiMap map = new FlexiMap();
            IBizObjList privileges = (IBizObjList)userGrp.get("appPrivileges");
			if (privileges.numElements > 0)
			{
				app.appData.get("Data.UserManagement.ClearGroupPrivileges", userGrp);
				for(int pos = 0; pos < privileges.numElements; pos++)
				{
					IBizObj priv = privileges[pos];
					if (!"-1".Equals(priv.get("privilege").ToString()))
					{
						map.put("albumId", priv.get("id").ToString());
						map.put("privilege", priv.get("privilege"));
						map.put("groupId", userGrp.get("id"));
						app.appData.get("Data.UserManagement.SetPrivilegeLevel", map);
					}
					else
						privileges.removeAt(pos--);
				}
			}
        }

        public void setUserUserGroupMembership(IApplication app, IRuleContext context, Swaf.BGuid.Guid userId, IBizObjList groupsToRemove, IBizObjList groupsToAdd)
        {
			try
			{
				if (userId != null)
				{
					FlexiMap m = new FlexiMap();
					m.put("userId", userId);
					if (groupsToRemove != null)
						foreach (IBizObj grp in groupsToRemove)
						{
							m.put("userGroupId", grp.get("id"));
							app.appData.put("DA.UserManagement.DeleteUserGroupLinkFromUser", m);
						}
					if(groupsToAdd != null)
						foreach (IBizObj grp in groupsToAdd)
						{
							m.put("id", new Swaf.BGuid.Guid());
							m.put("userGroupId", grp.get("id"));
							m.put("userId", userId);
							m.put("name", grp.get("name"));
							app.appData.put("DA.UserManagement.AddUserToGroup", m);
						}

					IBizObj user = app.appData.get("DA.UserLogin.GetUserDetails", m) as IBizObj;
					if (user == null)
						throw new UserManagementException("Unable to find user with provided id");

                    // setup the user preferences information
                    IResults rc = app.ruleMgr.execute("getUserPreferences", (Swaf.BGuid.Guid)user.get("id"));
                    if (rc.ExceptionInfo != null)
                        throw rc.ExceptionInfo;
                    user.put("settings", rc.CallResults);
                    LoginMgr.userUpdated(user, user.get("groups") as IBizObjList);

					//context.put("userId", user.get("id"));
					//Application.currentApp.appData.get("Data.UserManagement.ClearUserUserGroupLink", context);
					//IBizObjList grps = (IBizObjList)user.get("groups");
					////TODO: [ricky] remove the delete on AddUserToGroup dar once the grps list is resolve with duplicate
					//// items 
					//foreach (IBizObj grp in grps)
					//{
					//    map.put("id", Swaf.BGuid.Guid.NewGuid());
					//    map.put("userId", user.get("id"));
					//    map.put("groupId", grp.get("id"));
					//    map.put("name", grp.get("name"));

					//    app.appData.put("Data.UserManagement.AddUserToGroup", map);
					//}
					//LoginMgr.userUpdated(user, ((ICloneable)user.get("groups")).Clone() as IBizObjList);
				}
			}
			catch (Exception e)
			{
				throw new UserManagementException("Error exexuting setUserUserGroupMembership.", e);
			}
        }

		protected bool canUserManageCompany(IApplication app, Swaf.BGuid.Guid companyId)
		{
			Debug.Assert(companyId != null);
			Swaf.BGuid.Guid userCompanyId = (Swaf.BGuid.Guid)app.securityMgr.currentPrincipal.additionalInfo.get("companyId");
			Debug.Assert(userCompanyId != null);

			FlexiMap m = new FlexiMap();
			m.put("id", companyId);
			m.put("companyId", companyId);
			m.put("parentHostId", userCompanyId);
			
			IBizObjList l = (IBizObjList)app.appData.get("Data.UserManagement.GetUserManageCompanyInfo", m);
			IBizObjList c = (IBizObjList)app.appData.get("DA.UserLogin.GetCompany", m);
						
			return(l.numElements != 0 && (bool)c[0].get("canCreateChildCompanies") != false);
		}

		protected bool canCompanyCreateChildCompanies(IApplication app, Swaf.BGuid.Guid companyId)
		{
			try
			{
				//return (int)ActiveCompany.get("canCreateChildCompanies") != 0;
				if (companyId == null)
					return false;
				FlexiMap m = new FlexiMap();
				m.put("companyid", companyId);

				IBizObj c = app.appData.get("DA.UserManagement.GetCompanyCanHaveChildren", m) as IBizObj;
				return ((int)c.get("canCreateChildCompanies") != 0);
			}
			catch (Exception e)
			{
				throw new UserManagementException("Invalid company Id. No record found in the Company table for id: " + companyId.ToString(), e);
			}
		}

		protected void InsertCompanyRelations(IApplication app, Swaf.BGuid.Guid parentId, Swaf.BGuid.Guid companyId)
		{
			try
			{
				FlexiMap m = new FlexiMap();
				m.put("companyId", companyId);
				m.put("parentId", (parentId != null) ? parentId : companyId);

				IBizObjList l = (IBizObjList)app.appData.get("Data.UserLogin.GetCompanyParentPath", m);

				foreach (IBizObj c in l)
				{
					m.put("parentHostId", c.get("parentHostId"));
					app.appData.get("Data.UserManagement.InsertCompanyRelations", m);
				}
				m.put("parentHostId", companyId);
				app.appData.get("Data.UserManagement.InsertCompanyRelations", m);
			}
			catch (Exception e)
			{
				throw new UserManagementException("Error exexuting InsertCompanyRelations.", e);
			}
		}

		public string generateUserId(IApplication app, IRuleContext context, string appId, IBizObj user)
		{
			decimal clientId = 0;
			decimal accountId = -1;
			try
			{
				if (user == null)
					throw new UserManagementException("user is null.");
				clientId = Convert.ToDecimal(user.get("client.id"));
				accountId = Convert.ToDecimal(user.get("userAccountId"));

				string lname = user.get("lastName").ToString().Trim();
				string fname = user.get("firstName").ToString();
				string mi = user.get("middleName") == null ? "" : user.get("middleName").ToString().Trim();
				string userId = string.Format("{0}.{1}{2}", fname, mi.Length > 0 ? mi.Substring(0, 1) + "." : "", lname);

				userId = userId.Replace(" ", "").Replace("<", "").Replace(">", "").Replace("&", "").Replace("[", "").Replace("]", "").Replace("%", "").Replace("!", "");

				MatchCollection matches = new Regex(app.appData["InvalidUserIdRegex"].ToString()).Matches(userId);
				foreach (Match m in matches)
					if (m.Success)
						userId = userId.Replace(m.Groups[0].Value, "");

				if (userId.Length < 7)
					userId = string.Format("{0}{1}", userId.PadRight(6, '0'), "1");

				user.put("newUserId", string.Format("{0}%", userId));

				IBizObjList l = (IBizObjList)app.appData.get("Data.ClientManagement.GetClientUserIds", user);
				if (l.numElements > 0)
				{
					IBizObj usr = l[0];
					string id = usr.get("userId").ToString();
					id.Trim();
					Match m = new Regex(".*?(\\d+).*").Match(id);
					if (m.Success)
					{
						int val = System.Convert.ToInt32(m.Groups[1].Value);
						userId = string.Format("{0}{1}", id.Substring(0, id.IndexOf(val.ToString())), ++val);
					}
					else
						userId = string.Format("{0}{1}", userId, 1);

				}
				return userId;
			}
			catch (UserManagementException)
			{
				throw;
			}
			catch (Exception e)
			{
				string info = string.Format("An error occurred executing {0}. Error and Stack Message: {1} {2}",
						"generateUserId", e.Message, e.StackTrace);
				App.Log.println(Swaf.Logging.LoggingLevels.High, info);
				throw;

			}
		}
		/// <summary>
		/// Checks a password against the password policy to ensure it is valid
		/// </summary>
		/// <param name="Password">The password to validate</param>
		/// <returns>True if the password is valid, false otherwise</returns>
		//public bool IsValidPassword(string Password)
		//{
		//    StringBuilder regex = new StringBuilder();
		//    regex.Append("^([");

		//    string pwdString = new String(pwdCharArray);

		//    foreach (char chr in pwdCharArray)
		//    {
		//        regex.Append(chr.ToString());
		//    }

		//    foreach (char chr in pwdCharNonAlphaArray)
		//    {
		//        if (Char.IsDigit(chr) == false && chr.ToString() != "_")
		//        {
		//            regex.Append("\\" + chr.ToString());
		//        }
		//        else
		//        {
		//            regex.Append(chr.ToString());
		//        }
		//    }

		//    regex.Append("])");

		//    if (m_requireNonAlpha == true)
		//    {
		//        regex.Append("(?=.*[");
		//        foreach (char chr in pwdCharNonAlphaArray)
		//        {
		//            if (Char.IsDigit(chr) == false && chr.ToString() != "_")
		//            {
		//                regex.Append("\\" + chr.ToString());
		//            }
		//            else
		//            {
		//                regex.Append(chr.ToString());
		//            }
		//        }
		//        regex.Append("])");
		//    }

		//    foreach (char chr in exclusionSet)
		//    {
		//        if (Char.IsLetterOrDigit(chr) == false && chr.ToString() != "_")
		//        {
		//            regex.Append(@"(?!.*\" + chr.ToString() + ")");
		//        }
		//        else
		//        {
		//            regex.Append(@"(?!.*" + chr.ToString() + ")");
		//        }
		//    }

		//    regex.Append(".{" + (minSize - 1) + "," + (maxSize - 1) + "}$");

		//    System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(regex.ToString());

		//    return reg.IsMatch(Password);
		//}
    }
	public enum UserGroupSystemType {Generic=0, Admin, Anon};
}